package jee.boot.common.basic;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Lists;
import jee.boot.common.CommonConstant;
import jee.boot.common.annotation.*;
import jee.boot.common.basic.interceptor.*;
import jee.boot.common.basic.result.MapData;
import jee.boot.entity.auth.Account;
import jee.boot.entity.system.Filter;
import jee.boot.common.properties.ProjectConfig;
import jee.boot.common.utils.HttpServletHolder;
import jee.boot.common.utils.SpringContextHolder;
import jee.boot.common.utils.SpringEnvironmentHolder;
import jee.boot.common.utils.StringUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringEscapeUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

import static jee.boot.common.annotation.Column.Action;
import static jee.boot.common.annotation.DatabaseTime.Operate;

/**
 * 数据Entity类
 */
public abstract class DataEntity<T> extends BaseEntity<T> {
    private static final long serialVersionUID = 1L;
    /**
     * 有效数据
     */
    public static final String DATA_STATUS_ACTIVE = CommonConstant.DATA_STATUS_ACTIVE;
    /**
     * 无效数据
     */
    public static final String DATA_STATUS_INVALID = CommonConstant.DATA_STATUS_INVALID;
    /**
     * 被删除数据(逻辑)
     */
    public static final String DATA_STATUS_DELETED = CommonConstant.DATA_STATUS_DELETED;
    /**
     * 数据过滤器
     */
    @Transient
    protected List<Object> filter;

    /**
     * 附加条件是sql片段,不允许前端注入
     */
    @Transient
    private String additionalConditionsSql;

    /**
     * 创建账户
     */
    @Column(name = "create_by", data = {"createBy.id", "createBy.username", "createBy.name"})
    protected Account createBy;
    /**
     * 修改账户
     */
    @Column(name = "update_by", data = {"updateBy.id", "updateBy.username", "updateBy.name"})
    protected Account updateBy;
    /**
     * 创建日期
     */
    @DatabaseTime(operate = {Operate.INSERT})
    protected Date createDate;
    /**
     * 更新日期
     */
    @DatabaseTime(operate = {Operate.INSERT, Operate.UPDATE})
    protected Date updateDate;
    /**
     * 备注
     */
    protected String remarks;


    /**
     * 更新标志
     * 更新item时候使用
     */
    @Transient(ifDataIsNull = true)// 表示updateFlag有值的时候就进行查询,null值的时候就忽略查询
    protected String updateFlag;
    /**
     * 数据状态
     * 状态:Y:有效;N:无效;D:删除(逻辑)
     */
    protected String status;
    /**
     * 多租户ID
     */
    @Transient(ifDataIsNull = true)
    protected String tenant;

    // 非数据库字段
    /**
     * 是否为多租户模块
     */
    @Transient
    protected boolean tenantModule = true;
    /**
     * 外键,一对多操作时候使用,
     */
    @Transient
    protected String foreignKey;
    /**
     * 外键的值,一对多操作时候使用,
     */
    @Transient
    protected String foreignValue;
    /**
     * 批量操作时候的id列表
     */
    @Transient
    private List<String> idList;
    /**
     * 主数据缓存时候使用的key
     */
    @Transient
    private String cacheKey;
    /**
     * 使用Spring Cache缓存时候的对象的key值,entityKey=project.name+entity.id,主要是为不同项目进行命名空间的区分
     */
    @Transient
    private String entityKey;
    /**
     * 项目配置信息
     */
    @Transient
    private ProjectConfig projectConfig;
    /**
     * 是否启用审计字段,true:启用,动态sql中会包含审计字段;false:关闭,动态sql中不包含审计字段
     */
    @Transient
    private boolean enableAuditFields = true;
    /**
     * 忽略数据库操作的表名前的schema
     * true:  select * from at_user
     * false: select * from dim_dev.at_user
     */
    @Transient
    private boolean ignoreSchema = false;
    /**
     * 动态sql生成时候需要被忽略的属性名称,一般会在权限控制的时候通过拦截器的途径将权限之外的属性设置到这里面
     */
    @Transient
    private List<String> ignoreFieldNames = Lists.newArrayList();
    /**
     * 项目配置信息
     */
    @Transient
    private InterceptorRegister interceptorRegister;

    public DataEntity() {
        super();
    }

    public DataEntity(String id) {
        super(id);
    }


    /**
     * 插入之前执行方法，需要手动调用
     */
    @Override
    public void preInsert() {
        for (PreInsertInterceptor interceptor : getInterceptorRegister().getPreInsertInterceptorList()) {
            interceptor.execute(this);
        }
    }

    /**
     * 更新之前执行方法，需要手动调用
     */
    @Override
    public void preUpdate() {
        for (PreUpdateInterceptor interceptor : getInterceptorRegister().getPreUpdateInterceptorList()) {
            interceptor.execute(this);
        }
    }

    /**
     * 查询之前执行方法，需要手动调用
     */
    @Override
    public void preQuery() {
        for (PreQueryInterceptor interceptor : getInterceptorRegister().getPreQueryInterceptorList()) {
            interceptor.execute(this);
        }
    }

    /**
     * 插入之前执行方法，子类实现
     */
    @Override
    public void postInsert(Object data) {
        for (PostInsertInterceptor interceptor : getInterceptorRegister().getPostInsertInterceptorList()) {
            interceptor.execute(this, data);
        }
    }

    /**
     * 更新之前执行方法，子类实现
     */
    @Override
    public void postUpdate(Object data) {
        for (PostUpdateInterceptor interceptor : getInterceptorRegister().getPostUpdateInterceptorList()) {
            interceptor.execute(this, data);
        }
    }

    /**
     * 查询之前执行方法，子类实现
     */
    @Override
    public void postQuery(Object data) {
        for (PostQueryInterceptor interceptor : getInterceptorRegister().getPostQueryInterceptorList()) {
            interceptor.execute(this, data);
        }
    }

    /**
     * 使用Spring Cache缓存时候的对象的key值,entityKey=project.name+entity.id,主要是为不同项目进行命名空间的区分
     *
     * @return
     */
    @JsonIgnore
    public String getEntityKey() {
        if (StringUtils.isBlank(entityKey)) {
            entityKey = getProjectConfig().getName() + ":" + getId();
        }
        return entityKey;
    }

    public void setEntityKey(String entityKey) {
        this.entityKey = entityKey;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }

    // @JsonIgnore
    public Account getCreateBy() {
        return createBy;
    }

    public void setCreateBy(Account createBy) {
        this.createBy = createBy;
    }

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    // @JsonIgnore
    public Account getUpdateBy() {
        return updateBy;
    }

    public void setUpdateBy(Account updateBy) {
        this.updateBy = updateBy;
    }

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    public Date getUpdateDate() {
        return updateDate;
    }

    public void setUpdateDate(Date updateDate) {
        this.updateDate = updateDate;
    }

    @JsonIgnore
    public String getUpdateFlag() {
        return updateFlag;
    }

    public void setUpdateFlag(String updateFlag) {
        this.updateFlag = updateFlag;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getTenant() {
        return tenant;
    }

    public void setTenant(String tenant) {
        this.tenant = tenant;
    }

    @JsonIgnore
    public boolean isTenantModule() {
        return tenantModule;
    }

    public void setTenantModule(boolean tenantModule) {
        this.tenantModule = tenantModule;
    }

    public String getForeignKey() {
        return foreignKey;
    }

    public void setForeignKey(String foreignKey) {
        this.foreignKey = foreignKey;
    }

    public String getForeignValue() {
        return foreignValue;
    }

    public void setForeignValue(String foreignValue) {
        this.foreignValue = foreignValue;
    }

    public List<String> getIdList() {
        return idList;
    }

    public void setIdList(List<String> idList) {
        this.idList = idList;
    }

    @JsonIgnore
    public boolean isIgnoreSchema() {
        return ignoreSchema;
    }

    public void setIgnoreSchema(boolean ignoreSchema) {
        this.ignoreSchema = ignoreSchema;
    }

    @JsonIgnore
    public String getCacheKey() {
        return cacheKey;
    }

    public void setCacheKey(String cacheKey) {
        this.cacheKey = cacheKey;
    }

    public void setFilter(List<Object> filter) {
        this.filter = filter;
    }


    public List<Object> getFilter() {
        return filter;
    }

    @JsonIgnore
    public ProjectConfig getProjectConfig() {
        if (projectConfig == null) {
            try {
                projectConfig = SpringContextHolder.getApplicationContext().getBean(ProjectConfig.class);
            } catch (Exception e) {
                projectConfig = new ProjectConfig();
            }

        }
        return projectConfig;
    }

    public void setProjectConfig(ProjectConfig projectConfig) {
        this.projectConfig = projectConfig;
    }

    @JsonIgnore
    public boolean isEnableAuditFields() {
        return enableAuditFields;
    }

    public void setEnableAuditFields(boolean enableAuditFields) {
        this.enableAuditFields = enableAuditFields;
    }

    @JsonIgnore
    public List<String> getIgnoreFieldNames() {
        return ignoreFieldNames;
    }

    public void setIgnoreFieldNames(List<String> ignoreFieldNames) {
        this.ignoreFieldNames = ignoreFieldNames;
    }

    @JsonIgnore
    public InterceptorRegister getInterceptorRegister() {
        if (interceptorRegister == null) {
            try {
                interceptorRegister = SpringContextHolder.getApplicationContext().getBean(InterceptorRegister.class);
            } catch (Exception e) {
                interceptorRegister = new InterceptorRegister();
            }

        }
        return interceptorRegister;
    }


    /**
     * 根据设置的foreignKey转换成对应的columnName,如果设置的foreignKey本身就是columnName,那么直接返回foreignKey
     *
     * @param fieldMap
     * @param foreignKey
     * @return
     */
    protected String getColumnByForeignKey(Map<String, Field> fieldMap, String foreignKey) {
        if (fieldMap != null && !fieldMap.isEmpty()) {
            Field field = fieldMap.get(foreignKey);
            if (field != null) {
                String columnName = getColumnName(field);
                if (StringUtils.isNotBlank(columnName)) {
                    return columnName;
                }
            }
        }
        return foreignKey;
    }


    /**
     * 生成新增sql
     *
     * @return
     */
    @JsonIgnore
    public String getInsertSql() {
        AttrTable table = attrTable(Action.SAVE);
        StringBuilder sql = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        StringBuilder values = new StringBuilder();
        Map<String, Field> fieldAsMap = getFieldAsMap();
        for (AttrField f : table.getColumns()) {
            // 针对于OneToMany的子表数据新增,外键的值从foreignValue中获取
            if (StringUtils.equals(f.getColumn(), getColumnByForeignKey(fieldAsMap, getForeignKey()))) {
                f.setField("foreignValue");
            }
            columns.append(f.getColumn()).append(",");
            // 如果使用数据库时间作为审计字段的时间
            if (inOperatesArray(f.getOperates(), Operate.INSERT)) {
                values.append("now(),");
            } else {
                values.append("#{").append(f.getField()).append("},");
            }

        }
        sql.append("INSERT INTO ").append(table.getTableName()).append(" ( ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" ) VALUES ( ");
        sql.append(StringUtils.removeEnd(values.toString(), ",")).append(")");
        return sql.toString();
    }


    /**
     * 生成批量新增sql的columns部分的片段,在dao的注解中组装成完整sql
     *
     * @return
     */
    @JsonIgnore
    public String getBatchInsertColumnsSql() {
        AttrTable table = attrTable(Action.SAVE);
        StringBuilder sql = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        for (AttrField f : table.getColumns()) {
            columns.append(f.getColumn()).append(",");
        }
        sql.append("INSERT INTO ").append(table.getTableName()).append(" ( ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" ) VALUES ");
        return sql.toString();
    }

    /**
     * 生成批量新增sql的values部分的片段,在dao的注解中组装成完整sql
     *
     * @return
     */
    @JsonIgnore
    public String getBatchInsertValuesSql() {
        AttrTable table = attrTable(Action.SAVE);
        StringBuilder values = new StringBuilder();
        for (AttrField f : table.getColumns()) {
            // 如果使用数据库时间作为审计字段的时间
            if (inOperatesArray(f.getOperates(), Operate.INSERT)) {
                values.append("now(),");
            } else {
                values.append("#{entity.").append(f.getField()).append("},");
            }
        }
        return StringUtils.removeEnd(values.toString(), ",");
    }

    /**
     * 生成updateSql
     *
     * @return
     */
    @JsonIgnore
    public String getUpdateSql() {
        AttrTable table = attrTable(Action.UPDATE);
        StringBuilder sql = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        Map<String, Field> fieldAsMap = getFieldAsMap();
        for (AttrField f : table.getColumns()) {
            // 修改动作忽略id,createDate,createBy
            if (StringUtils.equals("id", f.getField()) || StringUtils.equals("createBy.id", f.getField()) || StringUtils.equals("createDate", f.getField())) {
                continue;
            }
            // 针对于OneToMany的子表数据修改,外键的值从foreignValue中获取
            if (StringUtils.equals(f.getColumn(), getColumnByForeignKey(fieldAsMap, getForeignKey()))) {
                f.setField("foreignValue");
            }
            // 如果使用数据库时间作为审计字段的时间
            if (inOperatesArray(f.getOperates(), Operate.UPDATE)) {
                columns.append(f.getColumn()).append(" = ").append("now(),");
            } else {
                columns.append(f.getColumn()).append(" = ").append("#{").append(f.getField()).append("},");
            }


        }
        sql.append("UPDATE ").append(table.getTableName()).append(" SET ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" WHERE ").append(table.getPrimaryColumn()).append("=").append("#{").append(table.getPrimaryField()).append("}");
        return sql.toString();
    }

    /**
     * 生成dynamicUpdateSql
     *
     * @return
     */
    @JsonIgnore
    public String getDynamicUpdateSql() {
        AttrTable table = attrTable(Action.UPDATE);
        StringBuilder sql = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        Map<String, Field> fieldAsMap = getFieldAsMap();
        for (AttrField f : table.getColumns()) {
            // 修改动作忽略id,createDate,createBy
            if (StringUtils.equals("id", f.getField()) || StringUtils.equals("createBy.id", f.getField()) || StringUtils.equals("createDate", f.getField())) {
                continue;
            }
            // 或略空值属性
            try {
                Object property = PropertyUtils.getProperty(this, f.getField());
                if (property == null) {
                    continue;
                }
            } catch (Exception e) {
                // 属性不存在的时候,直接忽略这个属性
            }
            // 针对于OneToMany的子表数据修改,外键的值从foreignValue中获取
            if (StringUtils.equals(f.getColumn(), getColumnByForeignKey(fieldAsMap, getForeignKey()))) {
                f.setField("foreignValue");
            }
            // 如果使用数据库时间作为审计字段的时间
            if (inOperatesArray(f.getOperates(), Operate.UPDATE)) {
                columns.append(f.getColumn()).append(" = ").append("now(),");
            } else {
                columns.append(f.getColumn()).append(" = ").append("#{").append(f.getField()).append("},");
            }


        }
        sql.append("UPDATE ").append(table.getTableName()).append(" SET ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" WHERE ").append(table.getPrimaryColumn()).append("=").append("#{").append(table.getPrimaryField()).append("}");
        return sql.toString();
    }

    /**
     * 生成删除sql
     *
     * @return
     */
    @JsonIgnore
    public String getDeleteSql() {
        AttrTable table = attrTable(Action.NULL);
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM ").append(table.getTableName());
        sql.append("  ");
        return sql.toString();
    }

    @JsonIgnore
    public String getLogicDeleteSql() {
        AttrTable table = attrTable(Action.NULL);
        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE ").append(table.getTableName());
        sql.append(" SET status='" + DataEntity.DATA_STATUS_DELETED + "'");
        sql.append(" WHERE ").append(table.getPrimaryColumn()).append("=").append("#{").append(table.getPrimaryField()).append("}");
        return sql.toString();
    }

    /**
     * 生成删除sql
     *
     * @return
     */
    @JsonIgnore
    public String getDeleteByUpdateFlagSql() {
        AttrTable table = attrTable(Action.NULL);
        StringBuilder sql = new StringBuilder();
        Map<String, Field> fieldAsMap = getFieldAsMap();
        String columnByForeignKey = getColumnByForeignKey(fieldAsMap, getForeignKey());
        sql.append("DELETE FROM ").append(table.getTableName());
        if (StringUtils.isNotBlank(columnByForeignKey)) {
            sql.append(" WHERE ").append(columnByForeignKey).append(" =#{foreignValue} and (update_flag!=#{updateFlag} or update_flag is null)");
        } else {//兼容旧版本的写法,
            sql.append(" WHERE head_id =#{head.id} and (update_flag!=#{updateFlag} or update_flag is null)");
        }
        return sql.toString();
    }

    /**
     * 生成删除sql
     *
     * @return
     */
    @JsonIgnore
    public String getDeleteByForeignKeySql() {
        AttrTable table = attrTable(Action.NULL);
        StringBuilder sql = new StringBuilder();
        Map<String, Field> fieldAsMap = getFieldAsMap();
        String columnByForeignKey = getColumnByForeignKey(fieldAsMap, getForeignKey());
        sql.append("DELETE FROM ").append(table.getTableName());
        sql.append(" WHERE ").append(columnByForeignKey).append(" =#{foreignValue}");
        return sql.toString();
    }


    /**
     * 生成GetSql
     *
     * @return
     */
    @JsonIgnore
    public String getGetSql() {
        AttrTable table = attrTable(Action.QUERY);
        List<JoinTable> joinTables = joinTable();
        StringBuilder sql = new StringBuilder();
        StringBuilder columns = new StringBuilder();

        for (AttrField f : table.getColumns()) {
            if (!f.isIgnoreAlias()) {
                columns.append("a.");
            }
            columns.append(f.getColumn()).append(" AS ").append("\"").append(f.getField()).append("\",");
        }
        if (!joinTables.isEmpty()) {
            for (JoinTable jt : joinTables) {
                for (AttrField f : jt.getColumns()) {
                    columns.append(f.getColumn()).append(" AS ").append("\"").append(f.getField()).append("\",");
                }
            }
        }
        sql.append("SELECT ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" FROM ").append(table.getTableName()).append(" a");
        if (!joinTables.isEmpty()) {
            for (JoinTable jt : joinTables) {
                sql.append(" ").append(jt.getJoin()).append(" ").append(jt.getTableName()).append(" ").append(jt.getAlias())
                        .append(" ON ").append(jt.getFkAlias()).append(".").append(jt.getFk()).append(" = ").append(jt.getAlias()).append(".").append(jt.getKey());
                if (StringUtils.isNotBlank(jt.getConditions())) {
                    sql.append(" ").append(jt.getConditions());
                }
            }
        }
        sql.append(" WHERE a.").append(table.getPrimaryColumn()).append("=").append("#{").append(table.getPrimaryField()).append("}");
        return sql.toString();
    }

    /**
     * 生成FindListSql
     *
     * @return
     */
    @JsonIgnore
    public String getFindListSql() {
        AttrTable table = attrTable(Action.QUERY);
        List<JoinTable> joinTables = joinTable();
        StringBuilder sql = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        for (AttrField f : table.getColumns()) {
            if (!f.isIgnoreAlias()) {
                columns.append("a.");
            }
            columns.append(f.getColumn()).append(" AS ").append("\"").append(f.getField()).append("\",");
        }
        if (!joinTables.isEmpty()) {
            for (JoinTable jt : joinTables) {
                for (AttrField f : jt.getColumns()) {
                    columns.append(f.getColumn()).append(" AS ").append("\"").append(f.getField()).append("\",");
                }
            }
        }
        sql.append("SELECT ");
        sql.append(StringUtils.removeEnd(columns.toString(), ","));
        sql.append(" FROM ").append(table.getTableName()).append(" a");
        if (!joinTables.isEmpty()) {
            for (JoinTable jt : joinTables) {
                sql.append(" ").append(jt.getJoin()).append(" ").append(jt.getTableName()).append(" ").append(jt.getAlias())
                        .append(" ON ").append(jt.getFkAlias()).append(".").append(jt.getFk()).append(" = ").append(jt.getAlias()).append(".").append(jt.getKey());
                if (StringUtils.isNotBlank(jt.getConditions())) {
                    sql.append(" ").append(jt.getConditions());
                }
            }
        }
        return sql.toString();
    }

    /**
     * 解析页面传入的排序属性
     *
     * @return
     */
    @JsonIgnore
    public String getOrderBySql() {
        StringBuilder defSql = new StringBuilder("ORDER BY a." + CommonConstant.AUDIT_COLUMN_UPDATE_DATE + " DESC");
        Page<T> page = getPage();
        if (page != null) {
            String orderBy = page.getOrderBy();
            String orderSort = page.getOrderSort();

            if (StringUtils.isNotBlank(orderBy)) {
                StringBuilder sql = new StringBuilder("ORDER BY ");
                String[] orderList = StringUtils.split(orderBy, ",");
                String[] sortList = null;
                if (StringUtils.isNotBlank(orderSort)) {
                    sortList = StringUtils.split(orderSort, ",");
                }

                for (int i = 0; i < orderList.length; i++) {
//                    String alias = page.getDefaultAlias();
                    String column;
                    String order = orderList[i];
                    String sort = "asc";
                    if (sortList != null) {
                        try {
                            //排序方法按着属性的位置在orderSort中获取,如果获取失败,则使用asc默认排序
                            sort = sortList[i];
                        } catch (Exception e) {

                        }
                    }
                    column = getColumnByFieldName(order);
                    // 设置表别名
//                    if (order.indexOf(".") > 0) {
//                        try {
//                            alias = order.substring(0, order.lastIndexOf("."));
//                            Field fieldByName = getFieldByName(alias);
//                            Class<?> clazz = fieldByName.getType();
//                            column = getColumnByFieldName(clazz, alias);
//                        } catch (Exception e) {
//                            logger.warn(e.getMessage(), e);
//                            column = getColumnByFieldName(order);
//                        }
//                    } else {
//                        column = getColumnByFieldName(order);
//                    }
                    sql.append(column).append(" ").append(sort).append(" ,");
                }
                return StringUtils.removeEnd(sql.toString(), ",");

            }
        }
        return defSql.toString();
    }

    /**
     * 检查数组中是否包含当前操作
     *
     * @param operates
     * @param operate
     */
    private boolean inOperatesArray(DatabaseTime.Operate[] operates, DatabaseTime.Operate operate) {
        if (operates == null || operates.length == 0) {
            return false;
        }
        for (DatabaseTime.Operate o : operates) {
            if (o.equals(operate)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 配置权限使用的附件条件
     *
     * @param additionalConditionsSql
     */
    public void configAdditionalConditionsSql(String additionalConditionsSql) {
        this.additionalConditionsSql = additionalConditionsSql;
    }


    /**
     * 添加查询filter <br>
     * <pre>  测试例子
     *  SysUser user = new SysUser();
     *         user.addFilter(new Filter("name", "=", "zhangsan"))
     *             .addFilter(new Filter("company.name", "like", "普华永道"))
     *             .addFilter(new Filter(
     *                     new Filter("office.id", "=", "1231"),
     *                     "or",
     *                     new Filter("office.name", "=", "沈阳研发")));
     *         System.out.println(user.getWhere());
     *         // and   a.name = 'zhangsan'   and   company.name like '%普华永道%'   and  (   office.id = '1231'   or   office.name = '沈阳研发'   )
     * </pre>
     *
     * @return
     */
    public <T extends BaseEntity> T addFilter(Filter filter) {
        if (getFilter() == null) {
            setFilter(new ArrayList<>());
        }
        getFilter().add(filter.toMap());
        return (T) this;
    }

    public <T extends BaseEntity> T addFilter(Map<String, Object> filter) {
        if (getFilter() == null) {
            setFilter(new ArrayList<>());
        }
        getFilter().add(filter);
        return (T) this;
    }

    public <T extends BaseEntity> T addFilter(List<Map<String, Object>> filter) {
        if (getFilter() == null) {
            setFilter(new ArrayList<>());
        }
        getFilter().add(filter);
        return (T) this;
    }

    /**
     * 生成where查询条件
     *
     * @return
     */
    @JsonIgnore
    public String getWhere() {
        List<String> sql = Lists.newArrayList();
        if (getFilter() != null && !getFilter().isEmpty()) {
            for (Object f : getFilter()) {
                sql.add(spliceSql(f));
            }
        }
        if (StringUtils.isNotBlank(additionalConditionsSql)) {
            sql.add(additionalConditionsSql);
        }
        return sql.isEmpty() ? "" : StringUtils.join(sql, "AND");
    }

    /**
     * 组装sql,标准数据结构的map进行sql的组装<br>
     * 规则:
     * <pre>
     *     map中至少要包含以下三个属性,left,operate,right
     *     left: 一个表达式左侧的数据,通常是类的属性(转换后变成表的字段)也可以是一个递归的结构体(同样要包含left,operate,right三个属性)
     *     operate: 操作,sql能支持的逻辑操作, 常用的包括 >,>=,<,<=,like,in等等,还包括 and,or 操作
     *     right: 一个表达式右侧的数据,通常是类属性的值,即查询条件的值,也可以是一个递归的结构体(同样要包含left,operate,right三个属性),另外,right还支持数组结构的数据List<String>
     *     demo1:
     *         {
     * 	         "left": "company.modeType",
     * 	         "operate": "=",
     * 	         "right": 123
     *         }
     *     demo2:
     *        {
     *             "left": {
     *                 "left": "company.modeType",
     *                 "operate": "=",
     *                 "right": 123
     *             },
     *             "operate": "or",
     *             "right": {
     *                 "left": "orgOffice.category",
     *                 "operate": "like",
     *                 "right": "category_1"
     *             }
     *         }
     * </pre>
     * <pre>
     *     转sql规则:
     *     left如果没有定义别名,如userName,则默认添加'a'作为别名(对应的sql查询需要使用a作为主表的别名), 如userName - > a.user_name
     *     left定义了别名,则使用对应的别名,如 orgOffice,则不另外设置别名,(对应的sql查询需要对应的join表设置相同的别名) 如orgOffice.companyName -> orgOffice.company_name
     *     right默认会用''将对应的值包起来,如果operate=like,则使用'%%'包裹,如果operate=in.则right应该为数组
     * </pre>
     *
     * @param data
     * @return
     */
    public String spliceSql(Object data) {
        if (data instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) data;
            String leftString;
            String rightString;
            Object left = map.get("left");
            String operate = (String) map.get("operate");
            boolean brackets = map.containsKey("brackets") ? (boolean) map.get("brackets") : false;
            boolean timestamp = map.containsKey("timestamp") ? (boolean) map.get("timestamp") : false;
            boolean exist = false;
            for (String o : CommonConstant.OPERATE_LIST) {
                if (StringUtils.containsIgnoreCase(o, operate)) {
                    exist = true;
                    break;
                }
            }
            if (!exist) {
                throw new ServiceException(1311, MapData.instance().put("operate", operate).data());
            }
            Object right = map.get("right");
            // 表达式左右的括号
            String bracketsLeft = "", bracketsRight = "";
            // 右侧表达式左右的百分号
            String percentSignLeft = "'", percentSignRight = "'";
            // 如果明确了要加括号,或者是or操作或者是子sql操作,需要对该表达式用()包起来
            if (brackets || StringUtils.equalsIgnoreCase("or", operate) || StringUtils.equalsIgnoreCase("sql", operate)) {
                bracketsLeft = "(";
                bracketsRight = ")";
                //如果是like操作,需要对该表达式用%%包起来
            } else if (StringUtils.equalsIgnoreCase("like", operate) || StringUtils.equalsIgnoreCase("not like", operate)) {
                percentSignLeft = "'%";
                percentSignRight = "%'";
            } else if (StringUtils.equalsIgnoreCase("left like", operate)) {
                operate = "like";
                percentSignLeft = "'%";
            } else if (StringUtils.equalsIgnoreCase("right like", operate)) {
                operate = "like";
                percentSignRight = "%'";
            } else if (StringUtils.equalsIgnoreCase("->", operate)) {
                // json 查询,忽略掉单引号
                percentSignLeft = "";
                percentSignRight = "";
            }
            // 处理左侧的表达式
            if (left instanceof Map) {
                leftString = spliceSql((Map) left);
            } else {
                String leftToString = left.toString();
                // 如果是sql子操作,不对left进行任何操作
                if (StringUtils.equalsIgnoreCase("built-in", operate)) {
                    leftString = leftToString;
                    operate = ""; // 忽略operate,直接在sql中拼接left即可
                } else if (StringUtils.equalsIgnoreCase("sql", operate)) {
                    leftString = StringEscapeUtils.escapeSql(leftToString);
                    operate = ""; // 忽略operate,直接在sql中拼接left即可
                } else {
                    leftString = getColumnByFieldName(leftToString);
                }
                if (timestamp) {
                    leftString = "UNIX_TIMESTAMP(" + leftString + ")*1000";
                }
            }
            // 处理右侧的表达式
            if (right == null) {
                // 这种情况可以适配无右侧表达式的情况,比如 user.id is null
                rightString = "";
            } else {
                if (right instanceof Map) {
                    rightString = spliceSql((Map) right);
                } else if (right instanceof List) {
                    rightString = "('" + StringUtils.join(escapeSqlList((List) right), "','") + "')";
                } else {
                    // 如果是in,not in操作,并且right为文本数据,则用逗号切割
                    if (StringUtils.equalsIgnoreCase("in", operate) || StringUtils.equalsIgnoreCase("not in", operate)) {
                        rightString = "('" + StringUtils.join(StringUtils.split(right.toString(), ","), "','") + "')";
                    } else {
                        rightString = percentSignLeft + StringEscapeUtils.escapeSql(right.toString()) + percentSignRight;
                    }

                }
            }
            return " " + bracketsLeft + " " + leftString + " " + operate + " " + rightString + " " + bracketsRight + " ";
        } else if (data instanceof List) {
            List<Map<String, Object>> list = (List<Map<String, Object>>) data;
            List<String> sql = Lists.newArrayList();
            for (Map<String, Object> map : list) {
                sql.add(spliceSql(map));
            }
            return sql.isEmpty() ? "" : "(" + StringUtils.join(sql, "OR") + ")";
        }
        return "";
    }

    /**
     * 生成当前entity所有需要关联的表
     *
     * @return
     */
    public List<JoinTable> joinTable() {
        List<JoinTable> list = new ArrayList<>();
        //获取所有的字段(包含父类)
        Collection<Field> fields = getFieldAsMap().values();
        for (Field field : fields) {
            // 跳过静态属性
            String mod = Modifier.toString(field.getModifiers());
            if (mod.indexOf("static") != -1) {
                continue;
            }
            // 跳过审计字段(如果不开启)
            if (!isEnableAuditFields()) {
                if (CommonConstant.AUDIT_FIELDS.contains(field.getName())) {
                    continue;
                }
            }
            // 是否忽略当前字段的存储
            Transient transientAnnotation = field.getAnnotation(Transient.class);
            // 为空表示需要存储当前字段
            if (transientAnnotation == null || transientAnnotation.ifDataIsNull()) {
                String fieldName = field.getName();
                String joinTableName;// 表名
                String fk = StringUtils.toUnderScoreCase(fieldName);//外键
                String alias = fieldName;//别名
                String key = null;//关联表字段,默认使用id进行关联,

                //查看是否定义了列属性
                Column columnAnnotation = field.getAnnotation(Column.class);
                // 如果定义了列属性,则使用定义的列属性作为fk
                if (columnAnnotation != null) {
                    if (StringUtils.isNotBlank(columnAnnotation.name())) {
                        fk = columnAnnotation.name();
                    }
                    if (StringUtils.isNotBlank(columnAnnotation.key())) {
                        key = columnAnnotation.key();
                    }
                }

                // 获取属性类型
                Class<?> typeClass = field.getType();
                //实例化
                Object typeClassInstance = null;
                try {
                    typeClassInstance = typeClass.newInstance();
                } catch (Exception e) {

                }
                // 前提: 必须是BaseEntity的子类对象,设置了Column注解,columnAnnotation为空,或者设置类column.joinTable=true
                if (typeClassInstance != null && typeClassInstance instanceof BaseEntity && (columnAnnotation == null || columnAnnotation.joinTable())) {
                    // 如果是对象类型,并且没有设置columnAnnotation.name属性,则fk应该在后面+_id
                    if (columnAnnotation == null || StringUtils.isBlank(columnAnnotation.name())) {
                        fk = fk + "_id";
                    }
                    // join 表的主键字段
                    Field primaryKey = getPrimaryKey(typeClass);
                    if (key == null && primaryKey != null) {
                        key = getColumnName(primaryKey);
                    }
                    if (key == null) {
                        key = "id";
                    }
                    joinTableName = getTableName(typeClassInstance.getClass());
                    // join 表中需要查询出来的字段
                    JoinTable joinTable = new JoinTable();
                    joinTable.setTableName(joinTableName);
                    joinTable.setAlias(alias);
                    joinTable.setFk(fk);
                    joinTable.setKey(key);
                    if (columnAnnotation != null) {
                        // 设置关联查询的关联类型
                        Column.JoinType joinType = columnAnnotation.joinType();
                        switch (joinType) {
                            case INNER_JOIN:
                                joinTable.setJoin(" INNER JOIN ");
                                break;
                            case RIGHT_JOIN:
                                joinTable.setJoin(" RIGHT JOIN ");
                                break;
                            default:
                                joinTable.setJoin(" LEFT JOIN ");

                        }
                        // 设置关联查询的附件条件
                        String[] conditions = columnAnnotation.extraConditions();
                        StringBuilder sb = new StringBuilder();
                        for (String c : conditions) {
                            sb.append(" and ").append(c);
                        }
                        if (StringUtils.isNotBlank(sb.toString())) {
                            joinTable.setConditions(sb.toString());
                        }
                        Map<String, Field> fieldAsMap = getFieldAsMap(typeClassInstance.getClass());
                        // 如果设置了自定义的外键table,则忽略 columnAnnotation.data()中的配置
                        if (columnAnnotation.fkTable().length > 0) {
                            // 这里我们只去第一个就好了,忽略后面的
                            FkTable fkTable = columnAnnotation.fkTable()[0];
                            joinTable.setFk(fkTable.columnName());
                            joinTable.setFkAlias(fkTable.alias());
                            String[] queryColumns = fkTable.queryColumns();
                            String[] queryFields = fkTable.queryFields();
                            int size = queryColumns.length <= queryFields.length ? queryColumns.length : queryFields.length;
                            for (int i = 0; i < size; i++) {
                                Field fieldByName = fieldAsMap.get(queryColumns[i]);
                                if (fieldByName != null) {
                                    joinTable.getColumns().add(new AttrField(queryFields[i], fieldName + "." + getColumnName(fieldByName), null));
                                }
                            }
                        } else {
                            // 如果定义了取数据的属性,则从定义中取值,
                            String[] columnAnnotationData = columnAnnotation.data();
                            for (String c : columnAnnotationData) {
                                // 默认id的查询是从主表("a")中查询
                                if (StringUtils.endsWith(c, ".id")) {
                                    continue;
                                }
                                String tn = StringUtils.substringBeforeLast(c, ".");
                                String fn = StringUtils.substringAfterLast(c, ".");
                                Field fieldByName = fieldAsMap.get(fn);
                                if (fieldByName != null) {
                                    joinTable.getColumns().add(new AttrField(c, tn + "." + getColumnName(fieldByName), null));
                                }
                            }
                        }
                    }
                    list.add(joinTable);


                }
            }

        }
        return list;

    }

    /**
     * 生成当前entity对应的表的基本信息以及所有字段
     *
     * @return
     */
    protected AttrTable attrTable() {
        return attrTable(Action.ALL);
    }

    /**
     * 生成当前entity对应的表的基本信息以及所有字段
     *
     * @param action 操作类型
     * @return
     */
    protected AttrTable attrTable(Action action) {
        AttrTable table = new AttrTable();
        //默认使用类名转小写作为表名
        String tableName = getTableName();
        //获取所有的字段(包含父类)
        Collection<Field> fields = getFieldAsMap().values();
        table.setTableName(tableName);
        // 如果不需要字段,直接返回
        if (Action.NULL.equals(action)) {
            return table;
        }
        for (Field field : fields) {
            // 跳过静态属性
            String mod = Modifier.toString(field.getModifiers());
            if (mod.indexOf("static") != -1) {
                continue;
            }
            // 跳过审计字段(如果不开启)
            if (!isEnableAuditFields()) {
                if (CommonConstant.AUDIT_FIELDS.contains(field.getName())) {
                    continue;
                }
            }
            // 设定主键
            PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class);
            if (primaryKey != null) {
                table.setPrimaryField(field.getName());
                table.setPrimaryColumn(getColumnName(field));
            }
            // 是否忽略当前字段的存储
            Transient transientAnnotation = field.getAnnotation(Transient.class);
            // 为空表示需要存储当前字段
            if (transientAnnotation == null || transientAnnotation.ifDataIsNull()) {
                String columnName = getColumnName(field);
                Object columnData = null;
                String fieldName = field.getName();
                //查看是否定义了列属性
                Column columnAnnotation = field.getAnnotation(Column.class);

                // 如果设置了fkTable表示这个字段仅仅是用来做joinTable的关联查询属性,不作为数据库存储字段
                if (columnAnnotation != null && columnAnnotation.fkTable().length > 0) {
                    continue;
                }

                Action columnAction = columnAnnotation == null ? Action.ALL : columnAnnotation.action();
                boolean ignoreAlias = columnAnnotation == null ? false : columnAnnotation.ignoreAlias();
                if (!Action.ALL.equals(action)) {
                    if (!Action.ALL.equals(columnAction)) {
                        if (!columnAction.equals(action)) {
                            continue;
                        }
                    }
                }

                try {
                    // 获取属性类型
                    Class<?> typeClass = field.getType();
                    //实例化
                    Object typeClassInstance = null;
                    //先从entity中获取当前属性的值,如果能获取到,那么直接使用当前值
                    Object data = PropertyUtils.getProperty(this, fieldName);
                    if (data != null) {
                        typeClassInstance = data;
                    } else {
                        // 如果获取不到属性值,则需要通过反射实例化一个类型的对象,来判断属性的是什么类型
                        try {
                            typeClassInstance = typeClass.newInstance();
                        } catch (Exception e) {
                        }
                    }
                    // 如果当前属性返回的数据是BaseEntity类型,即该字段是一个对象,那么默认取当前对象的id属性的值
                    if (typeClassInstance != null && typeClassInstance instanceof BaseEntity) {
//                        // 如果是对象类型,并且没有设置columnAnnotation.name属性,则column应该在后面+_id
//                        if (columnAnnotation == null || StringUtils.isBlank(columnAnnotation.name())) {
//                            columnName = columnName + "_id";
//                        }
                        // 如果定义了取数据的属性,则从定义中取值,

                        if (columnAnnotation != null && columnAnnotation.data() != null && columnAnnotation.data().length > 0) {
                            if (data != null) {
                                columnData = PropertyUtils.getProperty(this, columnAnnotation.data()[0]);
                            }
                            fieldName = columnAnnotation.data()[0];
                        } else {//否则取默认的id属性
                            if (data != null) {
                                columnData = PropertyUtils.getProperty(data, "id");
                            }
                            fieldName = fieldName + ".id";
                        }
                    } else {//否则直接读取当前属性的值
                        columnData = data;
                    }
                    if (transientAnnotation != null && transientAnnotation.ifDataIsNull() && columnData == null) {

                    } else {
//                        // 设置主键
//                        if (StringUtils.equals("id", fieldName)) {
//                            table.setPrimaryColumn("id");
//                            table.setPrimaryField("id");
//                            table.setPrimaryData(columnData);
//                        }
                        AttrField attrField = new AttrField(ignoreAlias, fieldName, columnName, columnData);
                        // 使用数据库时间
                        DatabaseTime databaseTime = field.getAnnotation(DatabaseTime.class);
                        if (databaseTime != null && getProjectConfig().isUseDatabaseTime()) {
                            attrField.setOperates(databaseTime.operate());
                        }
                        // 如果不在被忽略的属性名称之内,则加入到表的属性中用于后续的动态sql拼接
                        if (!ignoreFieldNames.contains(attrField.getField())) {
                            table.getColumns().add(attrField);
                        }
                    }
                } catch (NoSuchMethodException e) {
                    // 忽略没有get,set的属性,否则会报错
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }

            }

        }
        return table;
    }

    /**
     * 从当前类的定义中读取表名
     *
     * @return
     */
    @JsonIgnore
    public String getTableName() {
        return getTableName(getClass());
    }

    /**
     * 从当前类的定义中读取表名
     *
     * @param clazz
     * @return
     */
    @JsonIgnore
    protected String getTableName(Class<?> clazz) {
        String tableName;
        Table tableAnnotation = clazz.getAnnotation(Table.class);
        // 如果设置了table名称,则使用设置的
        if (tableAnnotation != null && StringUtils.isNotBlank(tableAnnotation.name())) {
            tableName = tableAnnotation.name();
        } else {//如果没设置,则使用entity的类名进行驼峰转换成表名
            tableName = StringUtils.toUnderScoreCase(clazz.getSimpleName());
        }
        String schema = getSchema();
        if (StringUtils.isNotBlank(schema) && !isIgnoreSchema()) {
            tableName = schema + "." + tableName;
        }
        return tableName;
    }

    /**
     * 读取schema
     *
     * @return
     */
    @JsonIgnore
    protected String getSchema() {
        return SpringEnvironmentHolder.getValue("spring.schema");
    }

    /**
     * 获取语言
     *
     * @return
     */
    @JsonIgnore
    protected String getLanguage() {
        return HttpServletHolder.getLanguage();
    }

    public String getColumnByFieldName(Class clazz, String fieldName) {
        return getColumnByFieldName(clazz, fieldName, true);
    }

    /**
     * 根据字段名查找列名
     *
     * @param fieldName
     * @return
     */
    public String getColumnByFieldName(Class clazz, String fieldName, boolean addAlias) {
        String columnName;
        // 如果在属性中找到同名的设置,按属性的绑定column进行设置
        Field field = getFieldByName(clazz, fieldName);
        if (field != null) {
            //查看是否定义了列属性
            Column columnAnnotation = field.getAnnotation(Column.class);
            // 如果定义了列属性,则使用定义的列属性作为column
            if (columnAnnotation != null && StringUtils.isNotBlank(columnAnnotation.name())) {
                if (addAlias) {
                    columnName = addAlias(columnAnnotation.name());
                } else {
                    columnName = columnAnnotation.name();
                }
            } else { // 否则使用当前字段名称进行驼峰转换作为column
                if (addAlias) {
                    columnName = turnUnderline(StringEscapeUtils.escapeSql(fieldName));
                } else {
                    columnName = StringUtils.toUnderScoreCase(StringEscapeUtils.escapeSql(fieldName));
                }
                Class<?> type = field.getType();
                try {
                    Object o = type.newInstance();
                    // 如果是对象类型的属性,则增加后缀_id
                    if (o instanceof BaseEntity) {
                        columnName += "_id";
                    }
                } catch (Exception e) {
                }
            }
        } else {// 配置的left未找到对应的java属性,则按配置的left转驼峰后进行设置
            if (addAlias) {
                columnName = turnUnderline(StringEscapeUtils.escapeSql(fieldName));
            } else {
                columnName = StringUtils.toUnderScoreCase(StringEscapeUtils.escapeSql(fieldName));
            }
        }
        return columnName;

    }

    /**
     * 根据字段名查找列名
     *
     * @param fieldName
     * @return
     */
    public String getColumnByFieldName(String fieldName) {
        String column;
        // 设置表别名
        if (fieldName.indexOf(".") > 0) {
            try {
                String alias = fieldName.substring(0, fieldName.lastIndexOf("."));
                String subFieldName = fieldName.substring(fieldName.lastIndexOf(".") + 1, fieldName.length());
                Field fieldByName = getFieldByName(alias);
                Class<?> clazz = fieldByName.getType();
                column = alias + "." + getColumnByFieldName(clazz, subFieldName, false);
            } catch (Exception e) {
                logger.warn(e.getMessage(), e);
                column = getColumnByFieldName(getClass(), fieldName);
            }
        } else {
            column = getColumnByFieldName(getClass(), fieldName);
        }
        return column;
    }

    /**
     * 对列表数据进行sql注入检测
     *
     * @param list
     * @return
     */
    protected List<String> escapeSqlList(List list) {
        List<String> retList = new ArrayList<>();
        list.forEach(o -> {
            retList.add(StringEscapeUtils.escapeSql(o.toString()));
        });
        return retList;
    }

    /**
     * 对string进行驼峰转下划线,并添加默认"a" 为表的别名,示例
     * <pre>
     *  name -> a.name
     *  userName -> a.user_name
     *  company.companyName -> company.company_name
     *  orgOffice.officeCode -> orgOffice.office_code
     * </pre>
     *
     * @param string
     * @return
     */
    protected String turnUnderline(String string) {
        if (StringUtils.isBlank(string)) {
            return "";
        }
        String defaultAlias = "a";
        if (string.indexOf(".") > 0) {
            defaultAlias = string.substring(0, string.lastIndexOf("."));
        }
        String field = StringUtils.toUnderScoreCase(string.substring(string.lastIndexOf(".") + 1));
        return defaultAlias + "." + field;
    }

    /**
     * 添加别名
     *
     * @param string
     * @return
     */
    private String addAlias(String string) {
        if (StringUtils.isBlank(string)) {
            return "";
        }
        if (string.indexOf(".") <= 0) {
            return "a." + string;
        }
        return string;
    }

    /**
     * 将属性列表转换为map
     *
     * @return
     */
    @JsonIgnore
    public Map<String, Field> getFieldAsMap(Class clazz) {
        Map<String, Field> map = new HashMap<>();
        //获取所有的字段(包含父类)
        while (clazz != null) {
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                // 子类属性,覆盖父类属性
                if (!map.containsKey(field.getName())) {
                    map.put(field.getName(), field);
                }
            }
            clazz = clazz.getSuperclass();
        }
        return map;
    }

    /**
     * 将属性列表转换为map
     *
     * @return
     */
    @JsonIgnore
    public Map<String, Field> getFieldAsMap() {
        return getFieldAsMap(getClass());
    }

    /**
     * 根据属性名称获取属性
     *
     * @param name
     * @return
     */
    protected Field getFieldByName(String name) {
        return getFieldByName(getClass(), name);
    }

    protected Field getFieldByName(Class clazz, String name) {
        Map<String, Field> map = getFieldAsMap(clazz);
        return map.get(name);
    }

    /**
     * 根据class类,查询该类的主键属性
     *
     * @param clazz
     * @return
     */
    protected Field getPrimaryKey(Class clazz) {
        Map<String, Field> map = getFieldAsMap(clazz);
        Collection<Field> fields = map.values();
        for (Field field : fields) {
            // 设定主键
            PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class);
            if (primaryKey != null) {
                return field;
            }
        }
        return null;
    }

    /**
     * 根据属性获取对应的列名
     *
     * @param field
     * @return
     */
    protected String getColumnName(Field field) {
        String columnName;
        //查看是否定义了列属性
        Column columnAnnotation = field.getAnnotation(Column.class);
        // 如果定义了列属性,则使用定义的列属性作为column
        if (columnAnnotation != null && StringUtils.isNotBlank(columnAnnotation.name())) {
            columnName = columnAnnotation.name();
        } else { // 否则使用当前字段名称进行驼峰转换作为column
            columnName = StringUtils.toUnderScoreCase(field.getName());
            try {
                // 获取属性类型
                Class<?> typeClass = field.getType();
                //实例化
                Object typeClassInstance = typeClass.newInstance();
                // 如果当前属性返回的数据是BaseEntity类型,即该字段是一个对象,那么默认取当前对象的id属性的值
                if (typeClassInstance != null && typeClassInstance instanceof BaseEntity) {
                    // 如果是对象类型,并且没有设置columnAnnotation.name属性,则column应该在后面+_id
                    if (columnAnnotation == null || StringUtils.isBlank(columnAnnotation.name())) {
                        columnName = columnName + "_id";
                    }
                }
            } catch (Exception e) {
                // 序列化失败,无视
            }

        }
        return columnName;
    }
}
